using System;
using System.Runtime.InteropServices;
using SLSearchNavSync.HelperClasses;
using SLSearchNavSync.TimerJobs;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace SLSearchNavSync.Features.SearchNavSyncTimerJob
{
    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>
    [Guid("0e8e0fcd-0b7e-47ee-97ad-01a73749f490")]
    public class SearchNavSyncTimerJobFeatureEventReceiver : SPFeatureReceiver
    {
        /// <summary>
        /// Feature activated event handler
        /// </summary>
        /// <param name="properties"></param>
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            try
            {
                //add an instance of the user profile sync timer job
                var webApp = (SPWebApplication)properties.Feature.Parent;
               
                //remove all the timer job instances
                RemoveAllTimerJob(webApp, Definitions.SearchNavigationSyncTimerJobName);
                
                //add the new timer jobs to the web app
                AddSearchNavigationSyncTimerJob(webApp);

                //activate the admin page feature
                var centralAdminWeb = SPContext.Current.Web;
                var adminPageFeatureGuid = new Guid(Definitions.SearchNavigationTimerJobAdminPagesFeatureId);
                var feature = centralAdminWeb.Features[adminPageFeatureGuid];
                if (feature == null) centralAdminWeb.Features.Add(adminPageFeatureGuid);
            }
            catch (Exception ex)
            {
                //log error
                UlsHelper.WriteUlsEntry(ex, TraceSeverity.Unexpected, EventSeverity.Error, Definitions.UlsCategory);
                //throw friendly error
                throw new SPException(String.Format(Definitions.MsgCouldntActivateFeature, properties.Definition.GetTitle(System.Globalization.CultureInfo.CurrentCulture)));
            }
        }

        /// <summary>
        /// Feature deactivating event handler
        /// </summary>
        /// <param name="properties"></param>
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            try
            {
                //add an instance of the user profile sync timer job
                var webApp = (SPWebApplication)properties.Feature.Parent;

                //remove all the timer job instances
                RemoveAllTimerJob(webApp, Definitions.SearchNavigationSyncTimerJobName);

                //deactivate the admin page feature if timer job isn't enabled on any web app
                if (!IsFeatureActiveOnOtherWebApp(webApp, properties.Feature.DefinitionId))
                {
                    var centralAdminWeb = SPContext.Current.Web;
                    var adminPageFeatureGuid = new Guid(Definitions.SearchNavigationTimerJobAdminPagesFeatureId);
                    var feature = centralAdminWeb.Features[adminPageFeatureGuid];
                    if (feature != null) centralAdminWeb.Features.Remove(adminPageFeatureGuid);
                }
            }
            catch (Exception ex)
            {
                //log error
                UlsHelper.WriteUlsEntry(ex, TraceSeverity.Unexpected, EventSeverity.Error, Definitions.UlsCategory);
                //throw friendly error
                throw new SPException(String.Format(Definitions.MsgCouldntDeactivateFeature, properties.Definition.GetTitle(System.Globalization.CultureInfo.CurrentCulture)));
            }
        }

        /// <summary>
        /// Adds a new Search Navigation Sync Timer Job to the web app
        /// </summary>
        /// <param name="webApp">The specified web application</param>
        private static void AddSearchNavigationSyncTimerJob(SPWebApplication webApp)
        {
            //create new timer job instance
            var searchNavSyncTimerJob = new SearchNavigationSyncTimerJobDefinition(Definitions.SearchNavigationSyncTimerJobName, webApp)
            {
                Title = Definitions.SearchNavigationSyncTimerJobTitle
            };

            var schedule = new SPHourlySchedule {BeginMinute = 15, EndMinute = 20};
            searchNavSyncTimerJob.Schedule = schedule;
            
            //update the timer job 
            searchNavSyncTimerJob.Update();
        }

        /// <summary>
        /// Removes all instances of the specified timer job from the web app
        /// </summary>
        /// <param name="webApp">The specified web application</param>
        /// <param name="strTimerJobName">Timer job name</param>
        private static void RemoveAllTimerJob(SPWebApplication webApp, string strTimerJobName)
        {
            //make sure the timer job isn't already registered
            foreach (var job in webApp.JobDefinitions)
            {
                if (job.Name == strTimerJobName)
                    job.Delete();
            }
        }

        /// <summary>
        /// Determins if the feature being checked is enabled on another web application
        /// </summary>
        /// <param name="curWebApp">Current SPWebApplication object</param>
        /// <param name="featureId">Guid of the feature ID</param>
        /// <returns>true if another web application has the feature activated, false otherwise</returns>
        private static bool IsFeatureActiveOnOtherWebApp(SPWebApplication curWebApp, Guid featureId)
        {
            var retVal = false;
            var services = SPFarm.Local.Services;

            foreach (var curService in services)
            {
                var webService = curService as SPWebService;
                if (webService != null)
                {
                    foreach (var webApp in webService.WebApplications)
                    {
                        if (webApp.Id == curWebApp.Id) continue;
                        if (webApp.Features[featureId] != null)
                        {
                            retVal = true;
                            break;
                        }
                    }
                }
            }

            return retVal;
        }

        #region Unused Events
        // Uncomment the method below to handle the event raised after a feature has been installed.

        //public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        //{
        //}


        // Uncomment the method below to handle the event raised before a feature is uninstalled.

        //public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        //{
        //}

        // Uncomment the method below to handle the event raised when a feature is upgrading.

        //public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
        //{
        //}
        #endregion
    }
}
